﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.Data.Services.Common;

namespace Azure.TableQuery.Core
{
    public class EntityQueryBuilder
    {
        private const string EntityFormat = @"
public class {0} : TableServiceEntity
{{
    {1}
}}

public class {0}Context : TableServiceContext, IAzureTableQuery
{{
    public {0}Context(string baseAddress, StorageCredentials credentials)
            : base(baseAddress, credentials)
    {{ }}

    public IQueryable<{0}> {0}
    {{
        get {{ return (from c in this.CreateQuery<{0}>(""{0}"") select c); }}
    }}
    
    public void OutputToGrid(DataGrid grid)
    {{
        grid.DataSource = ExecuteQuery();
        grid.DataBind();
    }}

    public MemoryStream OutputToXml(bool compress)
    {{
        var results = ExecuteQuery().ToArray<{0}>();
        
        MemoryStream stream = new MemoryStream();
        
        XmlSerializer serializer = new XmlSerializer(typeof({0}[]));
        serializer.Serialize(stream, results);
            
        if (!compress)
        {{
            return stream; 
        }}

        stream.Position = 0;
        MemoryStream compressedStream = new MemoryStream();
        
        CompressionUtility.Compress(stream, compressedStream, ""QueryResults"");

        return compressedStream;
    }}
   
    public IEnumerable<{0}> ExecuteQuery()
    {{
        var results = {2};

        if (results is IEnumerable<{0}>)
        {{
            return results;
        }}
        else
        {{
            return new List<{0}>() {{ ({0})results }};
        }}
    }}
}}

public class QueryContextFactory : IQueryContextFactory
{{
    public IAzureTableQuery CreateQueryContext(string baseAddress, StorageCredentials credentials)
    {{
        return new {0}Context(baseAddress, credentials);
    }}
}}
";
        private const string PropertyFormat = @"
public {0} {1} {{ get; set; }}
";

        private StringBuilder builder = new StringBuilder();
        public void AddQuery(GenericEntity entity, string queryText)
        {
            StringBuilder properties = new StringBuilder();
            var props = entity.GetProperties();
            foreach(var key in props.Keys)
            {
                if (key != "PartitionKey"
                    && key != "RowKey"
                    && key != "Timestamp")
                {
                    properties.AppendFormat(PropertyFormat,
                        props[key].FullName.ToString(),
                        key);
                }
            }

            System.Diagnostics.Trace.WriteLine(entity.GetTableName() + " Query: " + queryText);

            builder.AppendFormat(EntityFormat, 
                entity.GetTableName(),
                properties.ToString(),
                queryText);
            
        }

        public override string ToString()
        {
            return builder.ToString();
        }
    }
}
